package com.apobates.forum.attention.core;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.apobates.forum.utils.Commons;
/**
 * 上传图片的路径句柄
 * Schema(image://)
 * @author xiaofanku
 * @since 20190307
 */
public class UploadImagePathConvertHandler implements ImagePathDecodeHandler, ImagePathEncodeHandler{
	//图片的访问域名
	//http://center.test.com/
	private final String imageDomain;
	//imagestore
	private final String uploadDirectName;
	private final static String DIRECT="direct";
	private final static String FILE="file";
	//是否懒加载图片
	private final boolean lazyLoad;
	private final static Logger logger = LoggerFactory.getLogger(UploadImagePathConvertHandler.class);
	/**
	 * 
	 * @param imageDomain      图片存储的域名
	 * @param uploadDirectName 图片保存的目录名称
	 * @param lazyLoad         解码时内容中的图片是否时行懒加载; true进行懒加载,false直接加载
	 */
	public UploadImagePathConvertHandler(String imageDomain, String uploadDirectName, boolean lazyLoad) {
		super();
		this.imageDomain = imageDomain;
		this.uploadDirectName = uploadDirectName;
		this.lazyLoad = lazyLoad;
	}
	/**
	 * 适用于编码回复内容或编码或解码单张图片.解码回复内容的图片不要调用此方法
	 * 
	 * @param imageDomain      图片存储的域名
	 * @param uploadDirectName 图片保存的目录名称
	 */
	public UploadImagePathConvertHandler(String imageDomain, String uploadDirectName) {
		super();
		this.imageDomain = imageDomain;
		this.uploadDirectName = uploadDirectName;
		this.lazyLoad = false;
	}
	
	//http://center.test.com/imagestore/bridges-set-me-freerecord.jpg
	//
	//http://center.test.com/imagestore ==> image://defat
	@Override
	public Optional<String> encode(String content, ImageDirectoryEnum directoryEnum) {
		String lookUploadImgPrefix = imageDomain+"/"+uploadDirectName; //http://center.test.com/imagestore
		String replaceUploadImgPrefix = "image://"+directoryEnum.name().toLowerCase();
		//
		Document doc = Jsoup.parse(content);
		Elements imgTags = doc.select("img[src]");
		for(Element element : imgTags){
			String oldSrc = element.attr("src");
			if(oldSrc.startsWith(lookUploadImgPrefix)){
				element.attr("src", oldSrc.replace(lookUploadImgPrefix, replaceUploadImgPrefix).toLowerCase());
			}
		}
		return Optional.ofNullable(doc.body().html());
	}

	@Override
	public Optional<String> decode(String content, ImageDirectoryEnum directoryEnum, String scale) {
		String lookUploadImgPrefix = "image://"+directoryEnum.name().toLowerCase();
		//图片的尺寸@ADD
		logger.info("[SCALE][UploadImagePathConvertHandler]image scale: "+scale);
		String checkScale = checkImageScale(scale);
		logger.info("[SCALE][UploadImagePathConvertHandler]thumb scale: "+checkScale);
		Document doc = Jsoup.parse(content);
		Elements imgTags = doc.select("img[src]");
		for(Element element : imgTags){
			String oldSrc = element.attr("src");
			if(oldSrc.startsWith(lookUploadImgPrefix)){
				Map<String,String> pathInfo = getPathInfo(oldSrc, directoryEnum);
				String originalSrc = String.format("%s/thumbs/%s/%s/%s", imageDomain, pathInfo.get(DIRECT), checkScale, pathInfo.get(FILE));
				//
				if(lazyLoad){
					element.attr("class", "lazyload")
						.attr("src", "")
						.attr("data-scale", "resize")
						.attr("data-original", originalSrc); 
				}else{
					element.attr("src", originalSrc); 
				}
			}
		}
		return Optional.ofNullable(doc.body().html());
	}
	
	/**
	 * 对单个图片文件进行解码
	 * 
	 * @param encodeImageFilePath 编码的图片地址
	 * @param directoryEnum       图片存储源枚举
	 * @return
	 */
	public Optional<String> filePathDecode(String encodeImageFilePath, ImageDirectoryEnum directoryEnum){
		if(null==encodeImageFilePath){
			return Optional.empty();
		}
		String lookUploadImgPrefix = "image://"+directoryEnum.name().toLowerCase();
		String replaceUploadImgPrefix = imageDomain+"/"+uploadDirectName;
		String data = encodeImageFilePath.replace(lookUploadImgPrefix, replaceUploadImgPrefix).toLowerCase();
		return Optional.ofNullable(data);
	}
	
	/**
	 * 对单个图片文件进行解码并裁剪
	 * 
	 * @param encodeImageFilePath 编码的图片地址
	 * @param directoryEnum       图片存储源枚举
	 * @param scale               缩放比例.支持: 宽x高|auto
	 * @return
	 */
	public Optional<String> filePathDecode(String encodeImageFilePath, ImageDirectoryEnum directoryEnum, String scale){
		if(null==encodeImageFilePath){
			return Optional.empty();
		}
		String lookUploadImgPrefix = "image://"+directoryEnum.name().toLowerCase();
		if(encodeImageFilePath.startsWith(lookUploadImgPrefix)){
			Map<String,String> pathInfo = getPathInfo(encodeImageFilePath, directoryEnum);
			String originalSrc = String.format("%s/thumbs/%s/%s/%s", imageDomain, pathInfo.get(DIRECT), checkImageScale(scale), pathInfo.get(FILE));
			return Optional.ofNullable(originalSrc);
		}
		return Optional.empty();
	}
	/**
	 * 对单个图片文件进行编码
	 * 
	 * @param imageVisitPath 图片的访问(WEB)地址
	 * @param directoryEnum  图片存储源枚举
	 * @return
	 */
	public Optional<String> filePathEncode(String imageVisitPath, ImageDirectoryEnum directoryEnum){
		String lookUploadImgPrefix = imageDomain+"/"+uploadDirectName; //http://center.test.com/imagestore
		String replaceUploadImgPrefix = "image://"+directoryEnum.name().toLowerCase();
		String data = imageVisitPath.replace(lookUploadImgPrefix, replaceUploadImgPrefix).toLowerCase();
		return Optional.of(data);
	}
	
	/**
	 * 获得目录名和文件名
	 * 
	 * @param decodeImagePath
	 * @param directoryEnum
	 * @return
	 */
	private Map<String,String> getPathInfo(String encodeImageFilePath, ImageDirectoryEnum directoryEnum){
		String lookUploadImgPrefix = "image://"+directoryEnum.name().toLowerCase();
		String[] pathData = encodeImageFilePath.replace(lookUploadImgPrefix, "").split("/");
		//
		Map<String,String> data = new HashMap<>();
		data.put(DIRECT, "/");
		data.put(FILE, "");
		//
		if(pathData.length == 3){
			data.put(DIRECT, pathData[1]);
			data.put(FILE, pathData[2]);
		}
		if(pathData.length == 2){
			data.put(FILE, pathData[1]);
		}
		return data;
	}
	private String checkImageScale(String scale){
		if(null == scale){
			return "auto";
		}
		if(scale.indexOf("x")!=-1){
			String[] wh = scale.split("x");
			if(wh.length==2){
				return (Commons.isNumeric(wh[0]) && Commons.isNumeric(wh[1]))?scale:"auto";
			}
			return "auto";
		}
		return "auto";
	}
}
